package com.example.ff.limage;

import android.Manifest;
import android.app.ActivityManager;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Debug;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.widget.TextView;

import java.io.IOException;
import java.io.InputStream;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {

    private final String            TAG = "MainActivity";

    private TextView                mTxtMemory;
    private LargeImageView          mLargeImageView;


    private void printRect(Rect rect) {
        Log.e(TAG, "printRect:" + rect + " width = " + rect.width() + " height = " + rect.height());
    }

    private void test() {
        try {
            BitmapRegionDecoder decoder ;

            long begin, end;
            int width, height;
            BitmapFactory.Options options1,options2;
            Rect rect;
            Bitmap bitmap ;

            InputStream fs = getResources().getAssets().open("world_map.jpg");
            decoder = BitmapRegionDecoder.newInstance(fs,false);

            /*
            width = decoder.getWidth();
            height = decoder.getHeight();

            options1 = new BitmapFactory.Options();
            options1.inPreferredConfig = Bitmap.Config.RGB_565;
            options1.inSampleSize = 8;
            rect = new Rect(0, 0, width, height);

            begin = SystemClock.elapsedRealtime();
            bitmap = decoder.decodeRegion(rect, options1);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode and inBitmap = null " + " needs " + (end - begin));


            options2  = new BitmapFactory.Options();
            options2.inSampleSize = 8;
            options2.inMutable = true;
            options2.inPreferredConfig = Bitmap.Config.RGB_565;
            options2.inBitmap = bitmap;

            begin = SystemClock.elapsedRealtime();
            decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode and inBitmap = [bitmap] " + " needs " + (end - begin));


            int viewWidth = mImageView.getWidth(),viewHeight = mImageView.getHeight();
            options2  = new BitmapFactory.Options();
            options2.inSampleSize = 1;
            options2.inPreferredConfig = Bitmap.Config.ARGB_8888;

            rect = new Rect(0,0,viewWidth ,viewHeight);
            begin = SystemClock.elapsedRealtime();
            decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode width " + viewWidth + " height " + viewHeight + " needs " + (end - begin));



            viewWidth *= 2;
            viewHeight *= 2;

            rect = new Rect(0,0,viewWidth ,viewHeight);
            begin = SystemClock.elapsedRealtime();
            decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode width " + viewWidth + " height " + viewHeight + " needs " + (end - begin));

            viewWidth /= 4;
            viewHeight /= 4;

            rect = new Rect(0,0,viewWidth ,viewHeight);
            begin = SystemClock.elapsedRealtime();
            decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode width " + viewWidth + " height " + viewHeight + " needs " + (end - begin));





            rect = new Rect(0,0,mImageView.getWidth(),mImageView.getHeight());
            begin = SystemClock.elapsedRealtime();
            bitmap = decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode width " + viewWidth + " height " + viewHeight + " needs " + (end - begin));
*/

            // test

            options2  = new BitmapFactory.Options();
            options2.inSampleSize = 1;
            options2.inPreferredConfig = Bitmap.Config.ARGB_8888;

            int bitmapWidth = decoder.getWidth();
            int bitmapHeight = decoder.getHeight();

            rect = new Rect(0,0,720,1160);
            begin = SystemClock.elapsedRealtime();
            bitmap = decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode " + rect + " needs " + (end - begin) +
                    " bitmap.w = " + bitmap.getWidth() + " bitmap.h = " + bitmap.getHeight());


            rect = new Rect(0,0,bitmapWidth / 8,bitmapHeight / 8);
            begin = SystemClock.elapsedRealtime();
            bitmap = decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode " + rect + " needs " + (end - begin) +
                " bitmap.w = " + bitmap.getWidth() + " bitmap.h = " + bitmap.getHeight());


            rect = new Rect(0,0,bitmapWidth / 4,bitmapHeight / 4);
            begin = SystemClock.elapsedRealtime();
            bitmap = decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode " + rect + " needs " + (end - begin) +
                    " bitmap.w = " + bitmap.getWidth() + " bitmap.h = " + bitmap.getHeight());


            rect = new Rect(0,0,bitmapWidth / 2,bitmapHeight / 2);
            begin = SystemClock.elapsedRealtime();
            bitmap = decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode " + rect + " needs " + (end - begin) +
                    " bitmap.w = " + bitmap.getWidth() + " bitmap.h = " + bitmap.getHeight());

            rect = new Rect(0,0,bitmapWidth ,bitmapHeight );
            begin = SystemClock.elapsedRealtime();
            bitmap = decoder.decodeRegion(rect, options2);
            end = SystemClock.elapsedRealtime();
            Log.e(TAG, "test : decode " + rect + " needs " + (end - begin) +
                    " bitmap.w = " + bitmap.getWidth() + " bitmap.h = " + bitmap.getHeight());

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    void getMemory(){
        final float M = 1024 * 1024;
        final float G = M * 1024;

        ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);

        Debug.MemoryInfo debugMemory = new Debug.MemoryInfo();
        Debug.getMemoryInfo(debugMemory);

        ActivityManager.MemoryInfo memory = new ActivityManager.MemoryInfo();
        activityManager.getMemoryInfo(memory);

        Log.i(TAG, "otherPss : "    +  String.format("%.2f",debugMemory.otherPss / 1024.0f) + " M");
        Log.i(TAG, "nativePss : "   +  String.format("%.2f",debugMemory.nativePss / 1024.0f) + " M");
        Log.i(TAG, "dalvik : "      +  String.format("%.2f",debugMemory.dalvikPss / 1024.0f) + " M");


        Log.i(TAG, "availMem : "    +  String.format("%.2f",memory.availMem / M) + " M");
        Log.i(TAG, "totalMem : "    +  String.format("%.2f",memory.totalMem / M) + " M");
        Log.i(TAG, "threshold : "   +  String.format("%.2f",memory.threshold / M) + " M");
        Log.i(TAG, "lowMemory : "   +  memory.lowMemory );


        long total = debugMemory.otherPss + debugMemory.nativePss + debugMemory.dalvikPss  ;

        String str = "已申请 ";
        str += String.format("%.2f",total / 1024.0f) ;
        str += "/" + Runtime.getRuntime().maxMemory() / M + " M";
        Log.i(TAG, "total : "    +  total);

        str += "    剩余 ";
        str += String.format("%.2f",memory.availMem / G) ;
        str += "/" + String.format("%.2f",memory.totalMem / G) + " G";

        final SpannableString spanText = new SpannableString(str);
        if (memory.lowMemory || total > 96 * 1024){
            spanText.setSpan(new ForegroundColorSpan(Color.RED),4, 4 + String.format("%.2f",total / 1024.0f).length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        }else{
            spanText.setSpan(new ForegroundColorSpan(Color.WHITE),4,4 +  String.format("%.2f",total / 1024.0f).length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        }

        mTxtMemory.post(new Runnable() {
            @Override
            public void run() {
                mTxtMemory.setText(spanText);
            }
        });
    }
    void testMemory(){
        final float M = 1024 * 1024;
        ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);

        Runtime runtime = Runtime.getRuntime();
        float maxMemory = runtime.maxMemory() / M;
        float totalMemory = runtime.totalMemory() / M;
        float freeMemory = runtime.freeMemory() / M;

        Log.e(TAG, "maxMemory : " + String.format("%.2f",maxMemory) + " M ");
        Log.e(TAG, "totalMemory : " + String.format("%.2f",totalMemory) + " M ");
        Log.e(TAG, "freeMemory : " + String.format("%.2f",freeMemory) + " M ");

        float nativeHeapSize = android.os.Debug.getNativeHeapSize() / M;
        float nativeHeapAllocatedSize = android.os.Debug.getNativeHeapAllocatedSize() / M;
        float nativeHeapFreeSize = android.os.Debug.getNativeHeapFreeSize() / M;

        Log.e(TAG, "NativeHeapSizeTotal : "     + String.format("%.2f",nativeHeapSize) + " M");
        Log.e(TAG, "NativeAllocatedHeapSize : " +  String.format("%.2f",nativeHeapAllocatedSize) + " M");
        Log.e(TAG, "NativeAllocatedFree : "     +  String.format("%.2f",nativeHeapFreeSize) + " M");

        ActivityManager.MemoryInfo memory = new ActivityManager.MemoryInfo();
        activityManager.getMemoryInfo(memory);

        Log.e(TAG, "availMem : "    +  String.format("%.2f",memory.availMem / M) + " M");
        Log.e(TAG, "totalMem : "    +  String.format("%.2f",memory.totalMem / M) + " M");
        Log.e(TAG, "threshold : "    +  String.format("%.2f",memory.threshold / M) + " M");
        Log.e(TAG, "lowMemory : "   +  memory.lowMemory );


        Debug.MemoryInfo debugMemory = new Debug.MemoryInfo();
        Debug.getMemoryInfo(debugMemory);

        Log.e(TAG, "otherPss : "    +  String.format("%.2f",debugMemory.otherPss / 1024.0f) + " M");
        Log.e(TAG, "nativePss : "    +  String.format("%.2f",debugMemory.nativePss / 1024.0f) + " M");
        Log.e(TAG, "dalvik : "    +  String.format("%.2f",debugMemory.dalvikPss / 1024.0f) + " M");

        long total = debugMemory.otherPss + debugMemory.nativePss + debugMemory.dalvikPss  ;
        Log.e(TAG, "total : "    +  String.format("%.2f",total / 1024.0f) + " M");

    }
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
    }

    private String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};

    final int permissionCode = 13440;

    private void requestPermissions() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            int write = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (write != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(this, permissions, permissionCode);
            } else {

            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        Log.e(TAG, "permissions : ");
        for (String permission : permissions) {
            Log.e(TAG, " , " + permission);
        }

        Log.e(TAG, "grantResults : ");
        for (int grant : grantResults) {
            Log.e(TAG, " , " + grant);
        }
        if (requestCode == permissionCode && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //some work.
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
/*
        //去掉标题栏
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        //去掉信息栏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
*/
        setContentView(R.layout.activity_main);

        mTxtMemory = findViewById(R.id.txt_memory);

        mLargeImageView = findViewById(R.id.largeImageView);

        if (android.os.Build.VERSION.SDK_INT < 21) {
            requestPermissions();
        }

        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                getMemory();
            }
        };
        timer.schedule(task,1000 ,1000 * 1);
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    public void onTrimMemory(int level) {
        super.onTrimMemory(level);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mLargeImageView.destroyBitmaps();
    }

    @Override
    protected void onRestart() {
        super.onRestart();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        mLargeImageView.destroyBitmaps();
    }
}
